package com.js.data.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.js.data.common.constant.SymbolConstant;
import com.js.data.common.dto.SecurityUserDTO;
import com.js.data.common.exception.ApiException;
import com.js.data.common.utils.SecurityUtils;
import com.js.data.system.dto.DeptDTO;
import com.js.data.system.entity.SysDept;
import com.js.data.system.mapper.SysDeptMapper;
import com.js.data.system.mapper.SysUserMapper;
import com.js.data.system.service.DeptService;
import com.js.data.system.vo.CommonTreeVO;
import com.js.data.system.vo.DeptTreeVO;
import com.js.data.system.vo.SimpleUserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门 服务实现类
 * </p>
 *
 * @author wujj
 * @since 2022-09-06
 */
@Service
public class DeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements DeptService {


    @Resource
    private SysUserMapper sysUserMapper;



    /**
     * 部门列表
     *
     * @param parentId 父id
     * @return List<DeptListVO>
     */
    @Override
    public List<DeptTreeVO> treeDept(Long parentId) {
        List<DeptTreeVO> retList = new ArrayList<>();
        SecurityUserDTO currentUserInfo = SecurityUtils.getCurrentUserInfo();
        String permType = currentUserInfo.getPermType();
        if (parentId == 0) {
            // 管理员
            if (currentUserInfo.isAdmin()) {
                List<SysDept> list = lambdaQuery().eq(SysDept::getParentId, parentId).list();
                dbListTransform(list, retList, permType);
                return retList;
            }
            List<SysDept> list = listDeptByPerm(permType, currentUserInfo.getDeptId());
            if (permType.equals(SymbolConstant.FOUR_STR)) {
                excludeChild(list, retList);
            } else {
                dbListTransform(list, retList, permType);
            }
        } else {
            List<SysDept> list = lambdaQuery().eq(SysDept::getParentId, parentId).list();
            dbListTransform(list, retList, permType);
        }
        return retList;
    }

    /**
     * 新增部门
     *
     * @param deptDTO 部门表单
     */
    @Override
    public void saveDept(DeptDTO deptDTO) {
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(deptDTO, sysDept);
        Long pid = sysDept.getParentId();
        SysDept parentDept = null;
        if (pid != null && pid != 0) {
            parentDept = getById(pid);
            Optional.ofNullable(parentDept).orElseThrow(() -> new ApiException("父部门不存在"));
            sysDept.setParentIds(parentDept.getParentIds() + "," + pid);
        } else {
            sysDept.setParentIds(SymbolConstant.ZERO_STR);
        }
        sysDept.setSubCount(0);
        save(sysDept);
        // 数据保存成功,父级"直接子集数量"加1
        if (Objects.nonNull(pid)) {
            getBaseMapper().incrSubCount(pid);
        }
        // 数据保存成功,父级"直接子集数量"加1
        if (Objects.nonNull(parentDept)) {
            getBaseMapper().incrSubCount(pid);
        }

    }

    /**
     * 修改部门
     *
     * @param id      部门id
     * @param deptDTO 部门表单
     */
    @Override
    public void editDept(Long id, DeptDTO deptDTO) {
        SysDept sysDeptEX = getById(id);
        Optional.ofNullable(sysDeptEX).orElseThrow(() -> new ApiException("部门不存在"));
        Long newParentId = deptDTO.getParentId();
        if (id.equals(newParentId)) {
            throw new ApiException("上级不能为自己");
        }
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(deptDTO, sysDept);
        sysDept.setId(id);
        SysDept sysDeptEx = getById(id);
        // 修改了父节点
        if (!sysDeptEx.getParentId().equals(newParentId)) {
            // 原来上级子节点数量 -1
            getBaseMapper().decrSubCount(sysDeptEx.getParentId());
            // 现在上级子节点数量 +1
            getBaseMapper().incrSubCount(newParentId);
            SysDept parentDept = getById(newParentId);
            sysDept.setParentIds(parentDept.getParentIds() + "," + newParentId);
            //修改所有子节点的parentIds
            SysDept childDept = new SysDept();
            childDept.setParentIds(sysDept.getParentIds() + "," + id);
            List<Long> childIdList = getBaseMapper().selectAllChildIdByPid(id);
            lambdaUpdate().in(SysDept::getId, childIdList).update(childDept);
        }

        updateById(sysDept);


    }

    /**
     * 删除部门
     *
     * @param id 部门id
     */
    @Override
    public void deleteDept(Long id) {
        // 删除子节点
        SysDept sysDept = getById(id);
        Optional.ofNullable(sysDept).orElseThrow(() -> new ApiException("部门不存在"));
        removeById(id);
        List<Long> childIdList = getBaseMapper().selectAllChildIdByPid(id);
        this.removeByIds(childIdList);
        if (0 != sysDept.getParentId()) {
            SysDept parentDept = getById(sysDept.getParentId());
            Optional.ofNullable(parentDept).orElseThrow(() -> new ApiException("父部门不存在"));
            getBaseMapper().decrSubCount(parentDept.getParentId());
        }
        childIdList.add(id);
    }

    @Override
    public List<CommonTreeVO> treeSimpleDept(Long parentId, String orgType) {
        List<CommonTreeVO> retList = new ArrayList<>();
        if (SymbolConstant.TOW_STR.equals(orgType)) {
            List<Integer> currentUserHotel = SecurityUtils.getCurrentUserHotel();
            if (CollectionUtil.isEmpty(currentUserHotel)) {
                return retList;
            }
            List<SysDept> list = listByIds(currentUserHotel);
            dbListTransformSimple(list, retList);
            return retList;
        }
        if (parentId == 0) {
            SecurityUserDTO currentUserInfo = SecurityUtils.getCurrentUserInfo();
            // 管理员
            if (currentUserInfo.isAdmin()) {
                // 查询条件,部门的情况下从子节点查
                List<SysDept> list = lambdaQuery().eq(SysDept::getParentId, parentId).list();
                dbListTransformSimple(list, retList);
                return retList;
            }
            List<Long> deptIds = SecurityUtils.getCurrentUserDataScope();
            excludeChildSimple(listByIds(deptIds), retList);
            return retList;
        } else {
            List<SysDept> list = lambdaQuery().eq(SysDept::getParentId, parentId).list();
            dbListTransformSimple(list, retList);
        }
        return retList;
    }


    /**
     * 查询部门下所有的用户（包括子部门的用户）
     *
     * @param deptId 部门id
     * @return List<SimpleUserVO>
     */
    @Override
    public List<SimpleUserVO> listAllUserByDept(Long deptId) {
        SysDept sysDept = getById(deptId);
        Optional.ofNullable(sysDept).orElseThrow(() -> new ApiException("部门不存在"));
        List<Long> deptIds = getBaseMapper().selectAllChildIdByPid(deptId);
        deptIds.add(deptId);
        return sysUserMapper.selectSimpleUserByDept(deptIds);
    }

    /**
     * 查询部门下所以子部门,包含自己
     *
     * @param deptId 部门id
     * @return List<Integer>
     */
    @Override
    public List<Long> listAllChildDeptIdAndSelf(Long deptId) {
        List<Long> deptIds = getBaseMapper().selectAllChildIdByPid(deptId);
        deptIds.add(deptId);
        return deptIds;
    }

    /**
     * 查找所有部门
     *
     * @return List<Integer>
     */
    @Override
    public List<Long> listAllDept() {
        return lambdaQuery()
                .list().stream().map(SysDept::getId).collect(Collectors.toList());
    }

    /**
     * 数据库数据转换成返回数据
     *
     * @param dbList  数据库数据
     * @param retList 返回数据
     */
    private void dbListTransform(List<SysDept> dbList, List<DeptTreeVO> retList, String permType) {
        dbList.forEach(dept -> {
            DeptTreeVO deptTreeVO = new DeptTreeVO();
            BeanUtils.copyProperties(dept, deptTreeVO);
            if (permType.equals(SymbolConstant.TOW_STR)) {
                deptTreeVO.setSubCount(0);
            }
            retList.add(deptTreeVO);
        });
    }

    /**
     * 排除子部门
     *
     * @param dbList  数据库数据
     * @param retList 返回数据
     */
    private void excludeChild(List<SysDept> dbList, List<DeptTreeVO> retList) {
        dbList.forEach(dept -> {
            Long dbParentId = dept.getParentId();
            if (dbParentId == 0) {
                DeptTreeVO deptTreeVO = new DeptTreeVO();
                BeanUtils.copyProperties(dept, deptTreeVO);
                retList.add(deptTreeVO);
            } else {
                Optional<SysDept> any = dbList.stream().filter(d -> d.getId().equals(dbParentId)).findAny();
                if (!any.isPresent()) {
                    DeptTreeVO deptTreeVO = new DeptTreeVO();
                    BeanUtils.copyProperties(dept, deptTreeVO);
                    retList.add(deptTreeVO);
                }
            }
        });
    }

    /**
     * 数据库数据转换成返回数据
     *
     * @param dbList  数据库数据
     * @param retList 返回数据
     */
    private void dbListTransformSimple(List<SysDept> dbList, List<CommonTreeVO> retList) {
        dbList.forEach(dept -> {
            CommonTreeVO commonTreeVO = new CommonTreeVO();
            commonTreeVO.setId(dept.getId());
            commonTreeVO.setParentId(dept.getParentId());
            commonTreeVO.setName(dept.getShortName());
            commonTreeVO.setSubCount(dept.getSubCount());
            retList.add(commonTreeVO);
        });
    }

    /**
     * 排除子部门
     *
     * @param dbList  数据库数据
     * @param retList 返回数据
     */
    private void excludeChildSimple(List<SysDept> dbList, List<CommonTreeVO> retList) {
        dbList.forEach(dept -> {
            Long dbParentId = dept.getParentId();
            if (dbParentId == 0) {
                CommonTreeVO commonTreeVO = new CommonTreeVO();
                commonTreeVO.setId(dept.getId());
                commonTreeVO.setParentId(dept.getParentId());
                commonTreeVO.setName(dept.getShortName());
                commonTreeVO.setSubCount(dept.getSubCount());
                retList.add(commonTreeVO);
            } else {
                Optional<SysDept> any = dbList.stream().filter(d -> d.getId().equals(dbParentId)).findAny();
                if (!any.isPresent()) {
                    CommonTreeVO commonTreeVO = new CommonTreeVO();
                    commonTreeVO.setId(dept.getId());
                    commonTreeVO.setParentId(dept.getParentId());
                    commonTreeVO.setName(dept.getShortName());
                    commonTreeVO.setSubCount(dept.getSubCount());
                    retList.add(commonTreeVO);
                }
            }
        });
    }

    /**
     * 根据权限获取用户部门,查找部门的
     *
     * @param permType        权限
     * @param currentUserDept 当前用户部门
     * @return list
     */
    private List<SysDept> listDeptByPerm(String permType, Long currentUserDept) {
        // 用户数据权限  0-全部 1-本人 2-本部门 3-本部门及下级部门 4-指定
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        switch (permType) {
            case SymbolConstant.ZERO_STR:
                queryWrapper.eq(SysDept::getParentId, SymbolConstant.ZERO_INT);
                break;
            case SymbolConstant.ONE_STR:
            case SymbolConstant.TOW_STR:
            case SymbolConstant.THREE_STR:
                queryWrapper.eq(SysDept::getId, currentUserDept);
                break;
            case SymbolConstant.FOUR_STR:
                queryWrapper.in(SysDept::getId, SecurityUtils.getCurrentUserDataScope());
                break;
            default:
        }
        queryWrapper.eq(SysDept::getOrgType, SymbolConstant.ONE_STR);
        queryWrapper.orderByAsc(SysDept::getSortBy);
        return list(queryWrapper);
    }



}
